package com.naiterui.ehp.bs.doctor.dao.impl;

import cn.hutool.core.collection.CollectionUtil;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.google.common.collect.Lists;
import com.naiterui.ehp.bp.domain.Patient;
import com.naiterui.ehp.bp.domain.PatientPersonDoctor;
import com.naiterui.ehp.bp.domain.PatientPersonDoctorPK;
import com.naiterui.ehp.bs.doctor.dao.IPatientDao;
import com.naiterui.ehp.bs.doctor.repository.IPatientRepository;
import com.naiterui.ehp.bs.doctor.vo.PatientNameVO;

@Repository
public class AdPatientDaoImpl implements IPatientDao {
    private static final Logger LOGGER = LoggerFactory.getLogger(AdPatientDaoImpl.class);

    @Resource
    private EntityManager entityManager;

    @Autowired
    private IPatientRepository patientRepository;


    @Override
    public Patient get(Long id) {
        return this.patientRepository.get(id);
    }

    @Override
    public void saveOrUpdate(Patient patient) {

        if (patient.getId() == null) {
            this.patientRepository.save(patient);
        } else {
            patient.setChangedAt(new Date());
            this.patientRepository.update(patient);
        }
    }

    @Override
    public void update(Patient patient) {
        patient.setChangedAt(new Date());
        this.patientRepository.update(patient);
    }

    @Override
    public List<Patient> findAllPatientByIds(List<Long> patientIds) {
        if (CollectionUtil.isEmpty(patientIds)) {
            return null;
        }
        return this.patientRepository.findByIdIn(patientIds);
    }


    @Override
    public List<Long> findPatientListByDoctorId(Long doctorId) {

        // 查询粉丝id
        String sql = "select * from patient_personal_doctor where relation_flag = 0 and doctor_id = " + doctorId;
        Query query = this.entityManager.createNativeQuery(sql, PatientPersonDoctor.class);
        List<PatientPersonDoctor> list = query.getResultList();
        List<Long> result = Optional.ofNullable(list).orElse(Lists.newArrayList())
                                    .stream()
                                    .filter(Objects::nonNull)
                                    .map(PatientPersonDoctor::getPersonPK)
                                    .map(PatientPersonDoctorPK::getPatientId)
                                    .collect(Collectors.toList());

        return result;
    }


    /**
     * 根据医生ID患者姓名模糊查询患者名
     * <p>
     * 1.查询指定医生ID的患者，先查询设置过备注名的患者
     * 2.排除该医生设置备注名的所有患者,根据姓名或昵称查询
     * 3.合并查询结果
     * select pa.*,parn.remark_name from
     * (
     * select id,name,nick_name from patient where id in(select patient_id from
     * dr_patient_remarkname where doctor_id=15 and remark_name like '%强%')
     * UNION
     * select id,name,nick_name from patient
     * where
     * id in (select patient_id from patient_personal_doctor where doctor_id=15
     * and patient_id not in (select patient_id from dr_patient_remarkname where
     * doctor_id=15 and remark_name <> ''))
     * and
     * (name like '%强%' or (nick_name like '%强%' and (name='' or name is null))
     * )
     * ) as pa left join dr_patient_remarkname as parn on parn.doctor_id=15 and
     * pa.id=parn.patient_id
     * </p>
     * PatientDaoImpl.getPatientNameByDoctorId()
     *
     * @param doctorId
     * @param name
     *
     * @return
     *
     * @Author guoyongxiang
     * @Date 2016年2月27日
     * @since 2.2.0
     */
    @Override
    public Map<Long, PatientNameVO> getPatientNameByDoctorId(Long doctorId, String name) {

        StringBuilder bd = new StringBuilder();
        bd.append("select pa.*,parn.remark_name from ( ");
        // 查询设置备注名的
        /*
         * V2.5.0 用药列表添加患者头像 change by Gaoll 2016-06-21 14:46:08
         */
        bd.append("select id,name,nick_name,head_url from patient where id in(select patient_id from dr_patient_remarkname where doctor_id=?");
        if (StringUtils.isNotBlank(name)) {
            bd.append(" and remark_name like ?");
        }
        bd.append(")");

        bd.append(" UNION ");
        bd.append("select id,name,nick_name,head_url from patient where ");
        bd.append("id in (select patient_id from patient_personal_doctor where doctor_id=? and relation_flag = 0");
        bd.append(" and patient_id not in ( ");
        // 排除设置已备注名或备注名为空的用户(设置备注名的患者只能通过备注名搜索)
        bd.append("select patient_id from dr_patient_remarkname where doctor_id=? and remark_name <> ''))");
        if (StringUtils.isNotBlank(name)) {
            bd.append(" and (name like ? or (nick_name like ? and (name='' or name is null)) )");
        }
        bd.append(") as pa left join  dr_patient_remarkname as parn on parn.doctor_id=? and pa.id=parn.patient_id");

        Query query = this.entityManager.createNativeQuery(bd.toString());

        if (StringUtils.isNotBlank(name)) {
            // 字符串变量不加单引号(会被转义)
            String nameStr = "%" + name + "%";
            query.setParameter(1, doctorId)
                 .setParameter(2, nameStr)
                 .setParameter(3, doctorId)
                 .setParameter(4, doctorId)
                 .setParameter(5, nameStr)
                 .setParameter(6, nameStr)
                 .setParameter(7, nameStr);
        } else {
            query.setParameter(1, doctorId)
                 .setParameter(2, doctorId)
                 .setParameter(3, doctorId)
                 .setParameter(4, doctorId);
        }
        List<Object> objList = query.getResultList();

        Map<Long, PatientNameVO> paMap = new HashMap<>();
        if (objList != null && objList.size() > 0) {
            for (Object obj : objList) {
                Object[] column = (Object[]) obj;
                PatientNameVO vo = new PatientNameVO();
                vo.setId(((BigInteger) column[0]).longValue());
                String paName = (String) column[1];
                vo.setName(paName == null ? "" : paName);
                String paNickname = (String) column[2];
                vo.setNickname(paNickname == null ? "" : paNickname);
                String headUrl = (String) column[3];
                vo.setHeadUrl(headUrl == null || "/0".equals(headUrl) ? "" : headUrl);
                String paRemark = (String) column[4];
                vo.setRemarkName(paRemark == null ? "" : paRemark);
                paMap.put(vo.getId(), vo);
            }
        }
        return paMap;

    }

    /*
     * 获取患者map(id,实体)
     * IPatientDao.getPatientMap()
     */
    @Override
    public Map<Long, Patient> getPatientMap(Set<Long> patientIds) {

        Map<Long, Patient> resultMap = new HashMap<>();
        if (null != patientIds && !patientIds.isEmpty()) {
            List<Patient> patientList = this.patientRepository.findByIdIn(patientIds);
            if (null != patientList && !patientList.isEmpty()) {
                for (Patient patient : patientList) {
                    resultMap.put(patient.getId(), patient);
                }
            }
        }
        return resultMap;
    }

    /**
     * 根据医生Id查询患者列表
     *
     * @param doctorId
     *
     * @return
     *
     * @Author YongYang
     * @Date 2017年3月2日
     * @since 1.0.0
     */
    @Override
    public List<Long> findPatientList(Long doctorId) {
        String sql = "SELECT * FROM patient_personal_doctor WHERE relation_flag = 0 and doctor_id = ? and NOT EXISTS(SELECT * FROM patient PA WHERE PA.id = patient_id AND PA.account_status = 1)";
        Query query = this.entityManager.createNativeQuery(sql, PatientPersonDoctor.class);
        query.setParameter(1, doctorId);
        List<PatientPersonDoctor> list = query.getResultList();
        return list.stream().map(PatientPersonDoctor::getPersonPK).map(PatientPersonDoctorPK::getPatientId).collect(Collectors.toList());
    }

    /**
     * 批量查询患者id
     *
     * @return
     *
     * @Author YongYang
     * @Date 2017年3月2日
     * @since 1.0.0
     */
    @Override
    public List<Long> findPatientIdList(String patientIds) {
        List<Long> ids = Arrays.asList(StringUtils.split(patientIds, ",")).stream().map(Long::parseLong).collect(Collectors.toList());
        List<Patient> list = this.patientRepository.findByIdIn(ids);
        return list.stream().map(Patient::getId).collect(Collectors.toList());
    }

}
